﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CommHelper
{
    public static class DataConverter
    {
        /// <summary>
        /// 将字典copy到属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void DictCopyTo<T>(this Dictionary<string, object> source, T target) where T : class
        {
            if (source == null || source.Count == 0)
            {
                return;
            }
            if (target == null)
            {
                throw new ApplicationException("target 未实例化！");
            }

            var dic = source[source.Keys.First()] as Dictionary<string, object>;
            foreach (var result in dic.Keys)
            {
                string keyName = result;
                System.Reflection.PropertyInfo propertyInfo = target.GetType().GetProperty(keyName);
                if (propertyInfo == null) continue;

                if (((!propertyInfo.PropertyType.IsGenericType || !propertyInfo.PropertyType.GetGenericArguments()[0].IsEnum) && !propertyInfo.PropertyType.IsArray) &&
                                     ((!propertyInfo.PropertyType.IsGenericType || (propertyInfo.PropertyType.GetInterface("System.Collections.IEnumerable") == null))))
                {
                    object value = dic[keyName];
                    propertyInfo.SetValue(target, value, null);
                }
            }
        }

        /// <summary>
        /// 将字典copy到属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void DictCopyToList<T>(this Dictionary<string, object> source, List<T> target) where T : class
        {
            if (source == null)
            {
                return;
            }
            if (target == null)
            {
                throw new ApplicationException("target 未实例化！");
            }
            foreach (var result in source.Keys)
            {
                string keyName = result;
                System.Reflection.PropertyInfo propertyInfo = target.GetType().GetProperty(keyName);
                if (propertyInfo == null) continue;

                if (((!propertyInfo.PropertyType.IsGenericType || !propertyInfo.PropertyType.GetGenericArguments()[0].IsEnum) && !propertyInfo.PropertyType.IsArray) &&
                                     ((!propertyInfo.PropertyType.IsGenericType || (propertyInfo.PropertyType.GetInterface("System.Collections.IEnumerable") == null))))
                {
                    object value = source[keyName];
                    propertyInfo.SetValue(target, value, null);
                }
            }
        }

        public static void CopyTo<T>(this object source, T target) where T : class
        {
            if (source != null)
            {
                if (target == null)
                {
                    throw new ApplicationException("target 未实例化！");
                }
                foreach (PropertyInfo info in target.GetType().GetProperties())
                {
                    try
                    {
                        if (info.CanWrite && ((!info.PropertyType.IsGenericType || !info.PropertyType.GetGenericArguments()[0].IsEnum) && !info.PropertyType.IsArray) && ((!info.PropertyType.IsGenericType || (info.PropertyType.GetInterface("System.Collections.IEnumerable") == null)) && (source.GetType().GetProperty(info.Name) != null)))
                        {
                            if (info.PropertyType.IsEnum) continue;
                            object obj2 = source.GetType().GetProperty(info.Name).GetValue(source, null);
                            if ((obj2 != null) && !obj2.GetType().IsEnum)
                            {
                                target.GetType().InvokeMember(info.Name, BindingFlags.SetProperty, null, target, new object[] { obj2 });
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
                foreach (FieldInfo info2 in target.GetType().GetFields())
                {
                    if (info2.FieldType.IsArray || info2.FieldType.IsGenericType || info2.FieldType.IsEnum) continue;
                    if (null == source.GetType().GetField(info2.Name))
                    {
                        continue;
                    }
                    object obj3 = source.GetType().GetField(info2.Name).GetValue(source);
                    if (obj3 != null)
                    {
                        target.GetType().InvokeMember(info2.Name, BindingFlags.IgnoreCase, null, target, new object[] { obj3 });
                    }
                }
            }
        }

        public static void CopyTo_ToLower<T>(this object source, T target) where T : class
        {
            if (source != null)
            {
                if (target == null)
                {
                    throw new ApplicationException("target 未实例化！");
                }
                var TargetProperties = target.GetType().GetProperties();
                foreach (PropertyInfo info in source.GetType().GetProperties())
                {
                    string TranferName = info.Name.ToLower().Replace("_", "");
                    if (info.CanWrite && ((!info.PropertyType.IsGenericType || !info.PropertyType.GetGenericArguments()[0].IsEnum)
                        && !info.PropertyType.IsArray) && ((!info.PropertyType.IsGenericType || (info.PropertyType.GetInterface("System.Collections.IEnumerable") == null))))
                    {
                        if (info.PropertyType.IsEnum) continue;
                        PropertyInfo TargetInfo = TargetProperties.Where(x => x.Name.ToLower() == TranferName).FirstOrDefault();
                        if (TargetInfo == null) continue;

                        object obj = info.GetValue(source, null);
                        if (obj != null && !obj.GetType().IsEnum)
                        {
                            string value = obj.ToString();
                            if (!TargetInfo.PropertyType.IsGenericType)
                            {
                                TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, TargetInfo.PropertyType), null);
                            }
                            else
                            {
                                //泛型Nullable<>
                                Type genericTypeDefinition = TargetInfo.PropertyType.GetGenericTypeDefinition();
                                if (genericTypeDefinition == typeof(Nullable<>))
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(TargetInfo.PropertyType)), null);
                                }
                            }
                        }
                    }
                }
            }

            foreach (FieldInfo info2 in source.GetType().GetFields())
            {
                string TranferName = info2.Name.ToLower().Replace("_", "");
                var TargetFields = target.GetType().GetFields();
                FieldInfo FieldInfo = TargetFields.Where(x => x.Name.Replace("_", "").ToLower() == TranferName).FirstOrDefault();
                if (FieldInfo == null) continue;
                object obj = info2.GetValue(source);
                if (obj != null && !obj.GetType().IsEnum)
                {
                    string value = obj.ToString();
                    if (!FieldInfo.FieldType.IsGenericType)
                    {
                        FieldInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, FieldInfo.FieldType));
                    }
                    else
                    {
                        //泛型Nullable<>
                        Type genericTypeDefinition = FieldInfo.FieldType.GetGenericTypeDefinition();
                        if (genericTypeDefinition == typeof(Nullable<>))
                        {
                            FieldInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(FieldInfo.FieldType)));
                        }
                    }
                }
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="target">赋值字段</param>
        public static void CopyTo_ToLower_PropertyInfo_FieldInfo<T>(this object source, T target) where T : class
        {
            if (source != null)
            {
                if (target == null)
                {
                    throw new ApplicationException("target 未实例化！");
                }

                var TargetFields = target.GetType().GetFields();

                foreach (PropertyInfo info in source.GetType().GetProperties())
                {
                    string TranferName = info.Name.ToLower().Replace("_", "");
                    if (((!info.PropertyType.IsGenericType || !info.PropertyType.GetGenericArguments()[0].IsEnum) && !info.PropertyType.IsArray) && ((!info.PropertyType.IsGenericType || (info.PropertyType.GetInterface("System.Collections.IEnumerable") == null)) && (source.GetType().GetProperty(TranferName, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance) != null)))
                    {
                        if (info.PropertyType.IsEnum) continue;
                        FieldInfo TargetInfo = TargetFields.Where(x => x.Name.ToLower().Replace("_", "") == TranferName).FirstOrDefault();
                        if (TargetInfo == null) continue;

                        object obj = info.GetValue(source, null);
                        if (obj != null && !obj.GetType().IsEnum)
                        {
                            string value = obj.ToString();
                            if (!TargetInfo.FieldType.IsGenericType)
                            {
                                if (TargetInfo.FieldType == typeof(System.Boolean))
                                {
                                    TargetInfo.SetValue(target, value == null ? true : Convert.ToBoolean(int.Parse(value)));
                                }
                                else
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, TargetInfo.FieldType));
                                }
                            }
                            else
                            {
                                //泛型Nullable<>
                                Type genericTypeDefinition = TargetInfo.FieldType.GetGenericTypeDefinition();
                                if (genericTypeDefinition == typeof(Nullable<>))
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(TargetInfo.FieldType)));
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="target">赋值字段</param>
        public static void CopyTo_ToLower_PropertyInfo_FieldInfo1<T>(this object source, T target) where T : class
        {
            if (source != null)
            {
                if (target == null)
                {
                    throw new ApplicationException("target 未实例化！");
                }

                var TargetFields = target.GetType().GetFields();

                foreach (PropertyInfo info in source.GetType().GetProperties())
                {
                    string TranferName = info.Name.ToLower().Replace("_", "");
                    if (((!info.PropertyType.IsGenericType || !info.PropertyType.GetGenericArguments()[0].IsEnum) && !info.PropertyType.IsArray) && ((!info.PropertyType.IsGenericType || (info.PropertyType.GetInterface("System.Collections.IEnumerable") == null)) && (source.GetType().GetProperty(info.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance) != null)))
                    {
                        if (info.PropertyType.IsEnum) continue;
                        FieldInfo TargetInfo = TargetFields.Where(x => x.Name.ToLower().Replace("_", "") == TranferName).FirstOrDefault();
                        if (TargetInfo == null) continue;

                        object obj = info.GetValue(source, null);
                        if (obj != null && !obj.GetType().IsEnum)
                        {
                            string value = obj.ToString();
                            if (!TargetInfo.FieldType.IsGenericType)
                            {
                                if (TargetInfo.FieldType == typeof(System.Boolean))
                                {
                                    TargetInfo.SetValue(target, value == null ? true : Convert.ToBoolean(int.Parse(value)));
                                }
                                else
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, TargetInfo.FieldType));
                                }
                            }
                            else
                            {
                                //泛型Nullable<>
                                Type genericTypeDefinition = TargetInfo.FieldType.GetGenericTypeDefinition();
                                if (genericTypeDefinition == typeof(Nullable<>))
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(TargetInfo.FieldType)));
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// source为字段,target属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void CopyTo_ToLower_PropertyInfo_FieldInfo2<T>(this object source, T target) where T : class
        {
            if (source != null)
            {
                if (target == null)
                {
                    throw new ApplicationException("target 未实例化！");
                }

                var TargetFields = target.GetType().GetProperties();

                foreach (var info in source.GetType().GetFields())
                {
                    string TranferName = info.Name.ToLower().Replace("_", "");
                    if (((!info.FieldType.IsGenericType || !info.FieldType.GetGenericArguments()[0].IsEnum) && !info.FieldType.IsArray) && ((!info.FieldType.IsGenericType || (info.FieldType.GetInterface("System.Collections.IEnumerable") == null)) && (source.GetType().GetField(info.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance) != null)))
                    {
                        if (info.FieldType.IsEnum) continue;
                        var TargetInfo = TargetFields.Where(x => x.Name.ToLower().Replace("_", "") == TranferName).FirstOrDefault();
                        if (TargetInfo == null) continue;

                        object obj = info.GetValue(source);
                        if (obj != null && !obj.GetType().IsEnum)
                        {
                            string value = obj.ToString();
                            if (!TargetInfo.PropertyType.IsGenericType)
                            {
                                if (TargetInfo.PropertyType == typeof(System.Boolean))
                                {
                                    TargetInfo.SetValue(target, value == null ? true : Convert.ToBoolean(int.Parse(value)), null);
                                }
                                else
                                {
                                    TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, TargetInfo.PropertyType), null);
                                }
                            }
                            else
                            {
                                //泛型Nullable<>
                                Type genericTypeDefinition = TargetInfo.PropertyType.GetGenericTypeDefinition();
                                if (genericTypeDefinition == typeof(Nullable<>))
                                {
                                    if (Nullable.GetUnderlyingType(TargetInfo.PropertyType) == typeof(System.Int32) && info.FieldType == typeof(System.Boolean))
                                    {
                                        TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(Convert.ToInt32(Convert.ToBoolean(value)), Nullable.GetUnderlyingType(TargetInfo.PropertyType)), null);
                                    }
                                    else
                                    {
                                        TargetInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(TargetInfo.PropertyType)), null);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 字典类型转化为对象
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static void DicToEntity<T>(this Dictionary<string, object> dic, T target) where T : new()
        {
            if (target == null)
            {
                throw new ApplicationException("target 未实例化！");
            }
            foreach (var d in dic)
            {
                var filed = d.Key.ToLower().Replace("_", "");
                try
                {
                    var value = d.Value == null ? "" : d.Value.ToString();
                    var pInfos = target.GetType().GetProperties();
                    var pInfo = pInfos.Where(x => x.Name.ToLower() == filed).FirstOrDefault();
                    if (pInfo != null)
                    {
                        if (!pInfo.PropertyType.IsGenericType)
                        {
                            pInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, pInfo.PropertyType), null);
                        }
                        else
                        {
                            //泛型Nullable<>
                            Type genericTypeDefinition = pInfo.PropertyType.GetGenericTypeDefinition();
                            if (genericTypeDefinition == typeof(Nullable<>))
                            {
                                pInfo.SetValue(target, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(pInfo.PropertyType)), null);
                            }
                        }
                    }
                }
                catch
                {
                }
            }
        }
    }
}